#include "ServerSocket.h"
#include "Socket.h"
#include "PacketCapture.h"
#include "ThreadExecutor.h"
#include "PyPacketFilter.h"
#include "PySourceSetter.h"
#include "SendPacket.h"

/////////////////////////////////////////////////
/// Log <i>msg</i> if <i>e</i> not equal zero.
/////////////////////////////////////////////////
#define LOG_ON_ERRNO(e, msg)\
	if((e) != 0)\
	{\
		printf("Error on %s. errno = %d\n", (msg), (e));\
		return (e);\
	}

/////////////////////////////////////////////////
/// Print the usage of this program.
/////////////////////////////////////////////////
void usage(int argc, char* argv[])
{
	printf("Usage: %s <port>\n", argv[0]);
}

int main(int argc, char* argv[])
{
	if(argc < 2)
	{
		usage(argc, argv);
		return -1;
	}
	int port = atoi(argv[1]);
	ServerSocket serverSock;

	// Initialize server socket
	LOG_ON_ERRNO(serverSock.Init(), "serverSock.Init()");
	LOG_ON_ERRNO(serverSock.Bind(port), "serverSock.Bind(port)");
	LOG_ON_ERRNO(serverSock.Listen(), "serverSock.Listen()");

	while(true)
	{
		Socket sock;
		LOG_ON_ERRNO(serverSock.Accept(sock), "serverSock.Accept(sock)");
		PyPacketFilter pyPacketFilter;

		// Initialize packet sender
		SendPacket<PyPacketFilter> sendPacket(sock, pyPacketFilter);

		// Initialize the packet capturer with the packet sender operator
		PacketCapture<SendPacket<PyPacketFilter> > packetCapture(sendPacket);

		// Initialize the python source setter, receive python filter source from <i>sock</i>
		PySourceSetter pySourceSetter(sock, pyPacketFilter, packetCapture);

		// Set the packet capturer to the packet sender
		sendPacket.Init(&packetCapture);

		LOG_ON_ERRNO(packetCapture.Init(), "packetCapture.Init()");

		// Initialize a thread to execute the python source setter
		ThreadExecutor<PySourceSetter> threadExecutor(pySourceSetter);

		// Set the initial python filter: always drop packets(<i>ret</i> is always <i>False</i>)
		if(!pyPacketFilter.SetPySourceFilter("ret = False"))
			LOG_ON_ERRNO(errno, "pyPacketFilter.SetPySourceFilter(\"ret = False\")");

		// Execute the python source setter in a new thread
		threadExecutor();

		// Begin capture packets
		packetCapture();
	}
	return 0;
}
